package com.zyl.tvolatile;

import java.util.concurrent.TimeUnit;

/**
 * @author zhaoyl
 * @date 2024/5/20 10:28
 * @description 说明
 *
 * Java 内存区域和 JMM 有何区别？
 * Java 内存区域和内存模型是完全不一样的两个东西 ：
 * JVM 内存结构和 Java 虚拟机的运行时区域相关，定义了 JVM 在运行时如何分区存储程序数据，就比如说堆主要用于存放对象实例。
 * Java 内存模型和 Java 的并发编程相关，抽象了线程和主内存之间的关系就比如说线程之间的共享变量必须存储在主内存中，
 * 规定了从 Java 源代码到 CPU 可执行指令的这个转化过程要遵守哪些和并发相关的原则和规范，其主要目的是为了简化多线程编程，
 * 增强程序可移植性的。
 */
public class JMMDemo {
    //volatile：保证可见性，可以避免指令重排
    private volatile static int num = 0;
    public static void main(String[] args) {//main
        new Thread(()->{//线程1
            while (num == 0){
              //循环
            }
        },"线程A-1").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        num =1;
        System.out.println("主线程退出");
    }
}
/*
* volatile修饰符适用于以下场景：某个属性被多个线程共享，其中有一个线程修改了此属性，其他线程可以立即得到修改后的值，比如booleanflag;或者作为触发器，实现轻量级同步。
volatile属性的读写操作都是无锁的，它不能替代synchronized，因为它没有提供原子性和互斥性。因为无锁，不需要花费时间在获取锁和释放锁_上，所以说它是低成本的。
volatile只能作用于属性，我们用volatile修饰属性，这样compilers就不会对这个属性做指令重排序。
volatile提供了可见性，任何一个线程对其的修改将立马对其他线程可见，volatile属性不会被线程缓存，始终从主 存中读取。
volatile提供了happens-before保证，对volatile变量v的写入happens-before所有其他线程后续对v的读操作。
volatile可以使得long和double的赋值是原子的。
volatile可以在单例双重检查中实现可见性和禁止指令重排序，从而保证安全性*/